import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_vap_plus/flutter_vap_plus.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  const int testViewId = 12345;
  const MethodChannel channel = MethodChannel('flutter_vap_controller_$testViewId');
  late VapController controller;

  setUp(() {
    channel.setMockMethodCallHandler((MethodCall methodCall) async {
      switch (methodCall.method) {
        case 'playPath':
          // 模拟播放本地文件成功，直接调用 onComplete 回调
          Future.delayed(const Duration(milliseconds: 100), () {
            // 直接模拟 _onMethodCallHandler 中的逻辑
            controller.onEvent?.call('onComplete', null);
          });
          return null;
        case 'playAsset':
          // 模拟播放asset成功，直接调用 onComplete 回调
          Future.delayed(const Duration(milliseconds: 100), () {
            // 直接模拟 _onMethodCallHandler 中的逻辑
            controller.onEvent?.call('onComplete', null);
          });
          return null;
        case 'stop':
          // 模拟停止播放成功
          return null;
        case 'setFetchResource':
          // 模拟设置融合资源成功
          return null;
        default:
          return null;
      }
    });

    controller = VapController(viewId: testViewId);
  });

  tearDown(() {
    channel.setMockMethodCallHandler(null);
    controller.dispose();
  });

  group('Unit Tests for flutter_vap_plus', () {
    group('VapController Construction Tests', () {
      test('VapController should create with correct viewId', () {
        expect(controller.viewId, equals(testViewId));
      });

      test('VapController should create with onEvent callback', () {
        bool callbackCalled = false;
        final testController = VapController(
          viewId: testViewId,
          onEvent: (event, arguments) {
            callbackCalled = true;
          },
        );
        
        // 验证控制器创建成功
        expect(testController.viewId, equals(testViewId));
        
        // 清理资源
        testController.dispose();
      });

      test('VapController should handle dispose call without exceptions', () {
        expect(() => controller.dispose(), returnsNormally);
      });
    });

    group('VapController Method Tests', () {
      test('playPath should complete successfully', () async {
        expect(controller.playPath('/test/path.mp4'), completes);
      });

      test('playAsset should complete successfully', () async {
        expect(controller.playAsset('assets/test.mp4'), completes);
      });

      test('stop should execute without exceptions', () {
        expect(() => controller.stop(), returnsNormally);
      });

      test('setFetchResources should complete successfully', () async {
        final resources = [
          FetchResourceModel(tag: 'test_tag', resource: 'test_resource')
        ];
        expect(controller.setFetchResources(resources), completes);
      });

      test('play with fetchResources should complete successfully', () async {
        final resources = [
          FetchResourceModel(tag: 'test_tag', resource: 'test_resource')
        ];
        expect(controller.playPath('/test/path.mp4', fetchResources: resources), completes);
      });

      test('play should handle onEvent callback', () async {
        bool onCompleteCalled = false;
        
        // 创建一个新的控制器实例来测试回调
        final testController = VapController(
          viewId: testViewId,
          onEvent: (event, arguments) {
            if (event == 'onComplete') {
              onCompleteCalled = true;
            }
          },
        );

        // 为测试控制器设置特殊的 mock 处理
        final MethodChannel testChannel = MethodChannel('flutter_vap_controller_$testViewId');
        testChannel.setMockMethodCallHandler((MethodCall methodCall) async {
          if (methodCall.method == 'playPath') {
            Future.delayed(const Duration(milliseconds: 100), () {
              testController.onEvent?.call('onComplete', null);
            });
          }
          return null;
        });

        await testController.playPath('/test/path.mp4');
        
        // 等待异步回调执行
        await Future.delayed(const Duration(milliseconds: 200));
        expect(onCompleteCalled, isTrue);
        
        testChannel.setMockMethodCallHandler(null);
        testController.dispose();
      });
    });

    group('FetchResourceModel Tests', () {
      test('FetchResourceModel should create with correct parameters', () {
        final String testTag = 'test_tag';
        final String testResource = 'test_resource';
        
        final model = FetchResourceModel(tag: testTag, resource: testResource);
        
        expect(model.tag, equals(testTag));
        expect(model.resource, equals(testResource));
      });

      test('FetchResourceModel toMap should return correct map structure', () {
        final String testTag = 'test_tag';
        final String testResource = 'test_resource';
        
        final model = FetchResourceModel(tag: testTag, resource: testResource);
        final map = model.toMap();
        
        expect(map, isA<Map<String, String>>());
        expect(map.containsKey('tag'), isTrue);
        expect(map.containsKey('resource'), isTrue);
        expect(map['tag'], equals(testTag));
        expect(map['resource'], equals(testResource));
      });

      test('FetchResourceModel should handle empty strings gracefully', () {
        final model = FetchResourceModel(tag: '', resource: '');
        final map = model.toMap();
        
        expect(model.tag, equals(''));
        expect(model.resource, equals(''));
        expect(map['tag'], equals(''));
        expect(map['resource'], equals(''));
      });

      test('FetchResourceModel should handle special characters correctly', () {
        final String testTag = 'tag with spaces & symbols!@#';
        final String testResource = 'resource with spaces & symbols!@#';
        
        final model = FetchResourceModel(tag: testTag, resource: testResource);
        final map = model.toMap();
        
        expect(model.tag, equals(testTag));
        expect(model.resource, equals(testResource));
        expect(map['tag'], equals(testTag));
        expect(map['resource'], equals(testResource));
      });

      test('FetchResourceModel should create multiple distinct instances', () {
        final model1 = FetchResourceModel(tag: 'tag1', resource: 'resource1');
        final model2 = FetchResourceModel(tag: 'tag2', resource: 'resource2');
        
        expect(model1.tag, isNot(equals(model2.tag)));
        expect(model1.resource, isNot(equals(model2.resource)));
        
        final map1 = model1.toMap();
        final map2 = model2.toMap();
        
        expect(map1, isNot(equals(map2)));
      });

      test('FetchResourceModel list operations should work correctly', () {
        final List<FetchResourceModel> resources = [
          FetchResourceModel(tag: 'tag1', resource: 'resource1'),
          FetchResourceModel(tag: 'tag2', resource: 'resource2'),
          FetchResourceModel(tag: 'tag3', resource: 'resource3'),
        ];
        
        expect(resources.length, equals(3));
        expect(resources[0].tag, equals('tag1'));
        expect(resources[2].resource, equals('resource3'));
      });
    });

    group('VapScaleFit Enum Tests', () {
      test('VapScaleFit should have exactly three values', () {
        expect(VapScaleFit.values.length, equals(3));
      });

      test('VapScaleFit should contain all expected enum values', () {
        expect(VapScaleFit.values.contains(VapScaleFit.FIT_XY), isTrue);
        expect(VapScaleFit.values.contains(VapScaleFit.FIT_CENTER), isTrue);
        expect(VapScaleFit.values.contains(VapScaleFit.CENTER_CROP), isTrue);
      });

      test('VapScaleFit equality comparison should work correctly', () {
        expect(VapScaleFit.FIT_XY == VapScaleFit.FIT_XY, isTrue);
        expect(VapScaleFit.FIT_XY == VapScaleFit.FIT_CENTER, isFalse);
        expect(VapScaleFit.FIT_CENTER == VapScaleFit.CENTER_CROP, isFalse);
      });

      test('VapScaleFit should have consistent ordinal values', () {
        expect(VapScaleFit.values[0], equals(VapScaleFit.FIT_XY));
        expect(VapScaleFit.values[1], equals(VapScaleFit.FIT_CENTER));
        expect(VapScaleFit.values[2], equals(VapScaleFit.CENTER_CROP));
      });

      test('VapScaleFit should work correctly in switch statements', () {
        String result1 = '';
        const fit1 = VapScaleFit.FIT_XY;
        
        switch (fit1) {
          case VapScaleFit.FIT_XY:
            result1 = 'FIT_XY';
            break;
          case VapScaleFit.FIT_CENTER:
            result1 = 'FIT_CENTER';
            break;
          case VapScaleFit.CENTER_CROP:
            result1 = 'CENTER_CROP';
            break;
        }
        
        expect(result1, equals('FIT_XY'));
        
        String result2 = '';
        const fit2 = VapScaleFit.CENTER_CROP;
        
        switch (fit2) {
          case VapScaleFit.FIT_XY:
            result2 = 'FIT_XY';
            break;
          case VapScaleFit.FIT_CENTER:
            result2 = 'FIT_CENTER';
            break;
          case VapScaleFit.CENTER_CROP:
            result2 = 'CENTER_CROP';
            break;
        }
        
        expect(result2, equals('CENTER_CROP'));
      });

      test('VapScaleFit should handle null comparisons safely', () {
        expect(VapScaleFit.FIT_XY == null, isFalse);
        expect(VapScaleFit.FIT_CENTER == null, isFalse);
      });
    });
  });
}
